/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.component.recycle.maintain;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.jinhe.tss.component.recycle.RecycleConfig;
import com.jinhe.tss.component.recycle.RecycleInterceptor;
import com.jinhe.tss.component.recycle.RecycleResource;
import com.jinhe.tss.component.recycle.entity.Recycle;
import com.jinhe.tss.core.Global;
import com.jinhe.tss.core.exception.BusinessException;
import com.thoughtworks.xstream.XStream;

/**
 * <p> RecycleService.java </p>
 * <p>
 * Recycle的service层，负责处理Recycle相关的业务逻辑
 * </p>
 */
public class RecycleServiceImpl implements RecycleService {
	
    @Autowired private RecycleDao recycleDao;

	public void physicsDelete(Long recycleId) {
        Recycle recycle = getRecycle(recycleId);
        
        // 物理删除前先将回收拦截器在当前线程中关闭，这样删除的时候方可跳过拦截器
		RecycleInterceptor.switchTL.set(RecycleInterceptor.SWITCH_CLOSE_TAG);
        
		List<?> param = (List<?>)new XStream().fromXML(recycle.getParams());
		try {
			Object[] args = (Object[])param.get(0);
			Class<?>[] argTypes = (Class<?>[])param.get(1);
			
			Object dao = Global.getContext().getBean(recycle.getBeanId());
			Method removeMethodInDao = dao.getClass().getMethod(recycle.getMethodName(), argTypes);
            removeMethodInDao.invoke(dao, args);
            
		} catch (Exception e){
			throw new BusinessException("物理删除时出错:RecycleService.physicsDelete(Long)", e);
		}
		recycleDao.delete(recycle);
	}

	public void recover(Long recycleId) {
		Recycle recycle = getRecycle(recycleId);
	    
		// 刪除回收記錄
        recycleDao.delete(recycle);
        
		RecycleResource resource = RecycleConfig.getRecycleSource(recycle.getTypeId());

		/* 还原一起被删除的节点（Entity的recycleId一样 说明是同一次删除操作中删除的） */
		recycleDao.recoverByRecycleId(recycle.getEntityClass(), recycleId);
        
        //判断还原的对象是不是有层次结构的，如果有，则如果它的父节点也已经被删除，则需要将它的父亲节点一并还原（递归往上）
		if ( resource.isMultiLayer() ) {
			recoverParentNode(recycle.getEntityClass(), recycle.getNodeId());
		} 
	}

	/**
	 * 还原父结点。
     * 取出所有的父节点，遍历，如有打删除标记的则将其还原。
	 * 
	 * @param tableName
	 * @param nodeId
	 */
	private void recoverParentNode(String tableName, Long nodeId) {
		List<?> list = recycleDao.getParentNodes(tableName, nodeId);
        if (list == null) return;
            
        for(Iterator<?> it = list.iterator();it.hasNext();){
            Object obj[] = (Object[]) it.next();
            Long parentNodeId = (Long) obj[0];
            Integer deleted = (Integer) obj[1];
            if ( Recycle.TRUE.equals(deleted) ) {
                recycleDao.recoverParent(tableName, parentNodeId);
            }
        }
	}

    public List<?> getRecyledList(Integer typeId) {
        return recycleDao.getRecycleList(typeId);
    }

    public void clearAll(Integer typeId) {
        List<?> list = recycleDao.getRecycleList(typeId);
        for (Iterator<?> iter = list.iterator(); iter.hasNext();) {
            Recycle recycle = (Recycle) iter.next();
            physicsDelete(recycle.getId());
        }
    }
    
    private Recycle getRecycle(Long recycleId){
        Recycle recycle = (Recycle) recycleDao.getEntity(Recycle.class, recycleId);
        if(recycle == null) {
            throw new BusinessException("回收站中没有要还原数据的信息，请刷新页面确认是否已经还原！");
        }
        return recycle;
    }

}
